import time
from datetime import datetime
from nicegui import ui
import math
from common.third_party.devmem import DevMem
from random import randint
from settings import settings
from common.third_party.devmem import DevMemCache
from services.ad936x.api import Ad936xApi, DoubleGain, DoubleFrequency


AD_API = Ad936xApi()


def sync_ad3(index: int):
    SERVICE_CLOCK = 0x43C5_0000
    mem = DevMemCache()

    ad_index = [0, 0, 1, 1, 2, 2][index]
    gain = [20, 20, 15, 15, 15, 15][index]
    config = AD_API.get_config(ad_index)
    AD_API.set_gain(3, DoubleGain(gain_0=gain, gain_1=gain))
    AD_API.set_center_frequency(3, DoubleFrequency(
        rx_frequency=config.tx_frequency,
        tx_frequency=config.tx_frequency
    ))

    multiplexer_state = [4, 5, 3, 2, 1, 0][index]
    mem.get(SERVICE_CLOCK, 1)\
        .write(0, multiplexer_state)


def _read_pilot_word(index: int, offset: int):
    base_address = [0x83E0_0000, 0x83E1_0000, 0x83E5_0000][index]
    rdata = DevMem(address=base_address + offset * 4).read().get_value(True)
    return rdata


def _write_pilot_word(index: int, offset: int, value: int):
    base_address = [0x83E0_0000, 0x83E1_0000, 0x83E5_0000][index]
    DevMem(address=base_address + offset * 4).write(0, value)


def _pilot_field_select(word, start, end):
    l = end - start
    mask = (1 << l) - 1
    return (word >> start) & mask


def _read_pilot_power(index: int):
    amp_b = _pilot_field_select(_read_pilot_word(index, 10), 0, 24)
    return 0 if amp_b == 0 else (math.log10(amp_b) * 10)


def _read_status_of_link(self, index: int) -> bool:
    link = self._pilot_field_select(self._read_pilot_word(index, 11), 10, 11)
    return link == 1

def read_pilot_states(index: int):
    status = _pilot_field_select(_read_pilot_word(index, 11), 10, 11)
    amp_b = _pilot_field_select(_read_pilot_word(index, 10), 0, 24)
    pick_b = _pilot_field_select(_read_pilot_word(index, 8), 0, 24)

    power = 0.0 if amp_b == 0 else math.log10(amp_b) * 10
    pick = 0.0 if pick_b == 0 else math.log10(pick_b) * 10
    return status, power, pick

def make_monitor(index: int):
    with ui.row():
        with ui.card():
            status_label = ui.label('status: unknown')
            power_label = ui.label('power: 0')
            pick_label = ui.label('pick status: 0')

        with ui.card():
            log = ui.log().style('width:45em')

        with ui.card():
            def update():
                # sync_ad3(0)
                status, power, pick = read_pilot_states(index)

                status_label.text = f'status: {status}'
                power_label.text = f'power: {power}'
                pick_label.text = f'pick status: {pick}'

                time = datetime.now().strftime("%H:%M:%S")
                log.push(f'{time}: status: {status}, power: {power:.3f}, pick: {pick:.3f}')

            update_button = ui.button('update', on_click=update)
            auto_update_timer = ui.timer(1.8, update, active=False)
            auto_update_switch = ui.switch('auto update').bind_value(auto_update_timer, 'active')

make_monitor(0)
make_monitor(1)

ui.run(port=8800, title='debug', reload=False, loop="asyncio")
